package com.geezdata.cps.cqrs.event.listener.container;

import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.geezdata.cps.base.utils.ProxyUtil;
import com.geezdata.cps.cqrs.event.annotation.EventListener;
import com.geezdata.cps.cqrs.event.listener.Listener;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@SuppressWarnings("rawtypes")
public class ListenerContainer implements ApplicationContextAware, InitializingBean {
    private static Logger logger = LoggerFactory.getLogger(ListenerContainer.class);

    
	private Map<Class, List<Listener>> listenerMap;

    private ApplicationContext applicationContext;

	@SuppressWarnings("unchecked")
	public List<Listener> getListeners(Class eventClass) {
        return (List<Listener>) (listenerMap.get(eventClass) == null ? Lists.newArrayList() : listenerMap.get(eventClass));
    }

    public void setListenerMap(Map<Class, List<Listener>> listenerMap) {
        this.listenerMap = listenerMap;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception { 	
    	listenerMap = Maps.newHashMap();     
		Map<String, Listener> listeners = applicationContext.getBeansOfType(Listener.class);
        logger.info("Start init {}.", this.getClass().getSimpleName());

        if (listeners != null) {
            for (Map.Entry<String, Listener> entry : listeners.entrySet()) {
                Listener listener = (Listener) applicationContext.getBean(entry.getKey());
                listener = ProxyUtil.unwrapProxy(listener);
                EventListener eventListener = listener.getClass().getAnnotation(EventListener.class);

                if (eventListener != null && eventListener.event() != null) {
                    Class<?> eventClass = eventListener.event();
                    List<Listener> listenerList = listenerMap.get(eventClass);

                    logger.info(eventClass.getSimpleName() + " -> " + listener.getClass().getSimpleName());

                    if (listenerList == null) {
                        listenerMap.put(eventClass, Lists.newArrayList(listener));
                    } else {
                        listenerList.add(listener);
                    }
                }
            }
        }

        logger.info("Init {} success.", this.getClass().getSimpleName());
    }
}
